<?php
///////////////////////////////////////////////////////////////////////////////
/*
leaf.php

Class Leaf - class containing methods for retrieving and saving leaf data.


*/

class Leaf {

    private $id;
    private $parentnode_id;
    private $object_id;
    private $tablename;

    public static $TABLE_LEAF = TABLE_LEAF;


    /////////////////////////////////////////////////////////////////////////////
    // contructor - instantiates leaf object with supplied attributes
    public function __construct($id = null, $parentnode_id = null, $object_id = null, $tablename = null) {
        $this->init($id, $parentnode_id, $object_id, $tablename);
    }

    /////////////////////////////////////////////////////////////////////////////
    // init - convenience function to set all leaf attribute values at once
    public function init($id, $parentnode_id, $object_id, $tablename) {
        $this->setID($id);
        $this->setParentnodeID($parentnode_id);
        $this->setObjectID($object_id);
        $this->setTablename($tablename);
    }

    /////////////////////////////////////////////////////////////////////////////
    // load - initialize the leaf by loading it from the database based on the
    // specificed id
    public function load($id) {
        $sql = "SELECT id, parentnode_id, object_id, tablename " .
             "FROM " . Leaf::$TABLE_LEAF . " where id = " . $id;
        $result = DatabaseManager::getInstance()->query($sql);

        if ($row = $result->fetch_assoc()) {
            $this->init($row['id'], $row['parentnode_id'], $row['object_id'], $row['tablename']);
        } else {
            return false;
        }
        return true;
    }

    /////////////////////////////////////////////////////////////////////////////
    // insert - insert a new leaf into the database and return the new Leaf
    // Don't insert if it already exists.  That is, parent node id and object
    // node id combination already exists.
    public function insert() {

        if ($this->existsInDatabase()) {
            return false;
        }
        $sql = "CALL insertLeaf({$this->getParentnodeID()}, " .
                               "{$this->getObjectID()}, " .
                               "'{$this->getTablename()}', " .
                               "@newLeafID)";
        $result = DatabaseManager::getInstance()->query($sql);
        $sql = "select @newLeafID";
        $result = DatabaseManager::getInstance()->query($sql);
        if ($row = $result->fetch_assoc()) {
            $this->setID($row["@newLeafID"]);
        } else {
            return false;
        }
        return true;
    }

/*
    /////////////////////////////////////////////////////////////////////////////
    // insert - insert a new node into the database and return the new Node
    public function insert() {
        $sql = "CALL insertNode({$this->getParentnodeID()}, " .
                               "{$this->getLeveltypeID()}, " .
                               "'{$this->getName()}', " .
                               "'{$this->getDescription()}', " .
                               "'{$this->getWebaddress()}', " .
                               "@newNodeID)";
        //$result = DatabaseManager::getInstance()->getDatabaseConnection()->query($sql);
        $result = DatabaseManager::getInstance()->query($sql);
        $sql = "select @newNodeID";
        //$result = DatabaseManager::getInstance()->getDatabaseConnection()->query($sql);
        $result = DatabaseManager::getInstance()->query($sql);
        if ($row = $result->fetch_assoc()) {
            $this->setID($row["@newNodeID"]);
        } else {
            // some error handling?
            return false;
        }
        return true;
    }
*/










    /////////////////////////////////////////////////////////////////////////////
    // update - update the leaf to the database (leaf already exists in database)
    public function update() {
        $sql = "UPDATE " . Leaf::$TABLE_LEAF . " set parentnode_id = {$this->getParentnodeID()}, " .
                                   "object_id = {$this->getObjectID()}, " .
                                   "tablename = '{$this->getTablename()}' " .
               "WHERE id = {$this->getID()}";
        $result = DatabaseManager::getInstance()->query($sql);
    }

    /////////////////////////////////////////////////////////////////////////////
    // delete - delete the leaf from the database
    public function delete() {
        $sql = "DELETE FROM " . Leaf::$TABLE_LEAF . " WHERE id = {$this->getID()}";
        $result = DatabaseManager::getInstance()->query($sql);
        return true;
    }

    /////////////////////////////////////////////////////////////////////////////
    // existsInDatabase - checks to see if leaf already exists in database -
    // meaning a leaf record with parentnode_id and object_id both equal to
    // the values in this Leaf object.
    public function existsInDatabase() {
        $leafCount = 0;
        $sql = "SELECT count(*) as leaf_count FROM " . Leaf::$TABLE_LEAF .
               " where parentnode_id = {$this->getParentnodeID()} and object_id = {$this->getObjectID()} ";
        $result = DatabaseManager::getInstance()->query($sql);
        if ($row = $result->fetch_assoc()) {
            $leafCount = $row['leaf_count'];
        } else {
            // error handling?
        }
        if ($leafCount < 1) {
            return false;
        }
        return true;
    }

// Maybe implement isOrphan or something




    /////////////////////////////////////////////////////////////////////////////
    // getID - get the leaf id
    public function getID() {
        return $this->id;
    }

    /////////////////////////////////////////////////////////////////////////////
    // setID - set the leaf id
    public function setID($id) {
        $this->id = $id;
    }

    /////////////////////////////////////////////////////////////////////////////
    // getParentnodeID - get the parent node id
    public function getParentnodeID() {
        return $this->parentnode_id;
    }

    /////////////////////////////////////////////////////////////////////////////
    // setParentnodeID - set the parent node id
    public function setParentnodeID($parentnode_id) {
        $this->parentnode_id = $parentnode_id;
    }

    /////////////////////////////////////////////////////////////////////////////
    // getObjectID - get the object id
    public function getObjectID() {
        return $this->object_id;
    }

    /////////////////////////////////////////////////////////////////////////////
    // setObjectID - set the object id
    public function setObjectID($object_id) {
        $this->object_id = $object_id;
    }

    /////////////////////////////////////////////////////////////////////////////
    // getTablename - get the tablename
    public function getTablename() {
        return $this->tablename;
    }
    /////////////////////////////////////////////////////////////////////////////
    // setTablename - set the tablename
    public function setTablename($tablename) {
        $this->tablename = $tablename;
    }

    /////////////////////////////////////////////////////////////////////////////
    // printLeafData - debug function that dumps leaf attributes
    public function printLeafData($desc = "") {
        //print("--------------------------------------------\n");
        print("{$desc}:\n");
        print("\tID: {$this->getID()}\n");
        print("\tPARENT ID: {$this->getParentnodeID()}\n");
        print("\tOBJECT ID: {$this->getObjectID()}\n");
        print("\tTABLE NAME: {$this->getTablename()}\n");
    }




    // Static functions - mainly for retrieving groups of leafs

    /////////////////////////////////////////////////////////////////////////////
    public static function loadLeafs($condition) {
        $leafs = array();
        $sql = "SELECT id, parentnode_id, object_id, tablename FROM " .
               Leaf::$TABLE_LEAF . " where " .
               $condition;
        $result = DatabaseManager::getInstance()->query($sql);
        while ($row = $result->fetch_assoc()) {
            $leaf = new Leaf($row['id'],
                             $row['parentnode_id'],
                             $row['object_id'],
                             $row['tablename']);
            $leafs[] = $leaf;
        }
        return $leafs;
    }



    /////////////////////////////////////////////////////////////////////////////
    // loadLeafsForNodes - given a list of nodes, return a new array containing:
    //     - key = node ID
    //     - value = array of leafs
    // used for fetching multiple arrays of leafs for a set of nodes
    public static function loadLeafsForNodes($nodes) {
        $nodeLeafs = array();
        foreach ($nodes as $node) {
            $leafs = Leaf::loadLeafsOfNode($node);
            if (count($leafs) > 0) {
                $nodeLeafs[$node->getID()] = $leafs;
            }
        }
        return $nodeLeafs;
    }

    /////////////////////////////////////////////////////////////////////////////
    // loadLeafsOfNodeID - given a node ID, return an array of leafs
    public static function loadLeafsOfNodeID($node_id) {
        $leafs = array();
        Leaf::loadLeafsOfNodeIDRecursive($node_id, $leafs);
        return $leafs;
    }

    /////////////////////////////////////////////////////////////////////////////
    // loadLeafsOfNode - given a Node, return an array of leafs
    public static function loadLeafsOfNode($node) {
        return Leaf::loadLeafsOfNodeID($node->getID());
    }

    /////////////////////////////////////////////////////////////////////////////
    // loadLeafsOfNodeIDRecursive - does the dirty work for getLeafsOfNodeID
    public static function loadLeafsOfNodeIDRecursive($node_id, &$leafs) {
        $newleafs = Leaf::loadLeafsOfParentNodeID($node_id);
        //print("newleafs count: " . count($newleafs) . "\n");
        //$leafs = $leafs + $newleafs;
        $leafs = array_merge($leafs, $newleafs);
        //print("leafs count: " . count($leafs) . "\n");
        $childNodes = Node::loadNodes('parentnode_id = ' . $node_id);
        //print("childNodes count: " . count($childNodes) . "\n");
        foreach ($childNodes as $childNode) {
            // Leaf::loadLeafsOfNodeIDRecursive($childNode['id'], $leafs);
            Leaf::loadLeafsOfNodeIDRecursive($childNode->getID(), $leafs);
        }
    }

    /////////////////////////////////////////////////////////////////////////////
    // loadLeafsOfParentNodeID - given a node ID, return the leafs directly under
    // it (i.e. directly assigned, not skipping levels, etc.)
    public static function loadLeafsOfParentNodeID($parentnode_id) {
        return(Leaf::loadLeafs('parentnode_id = ' . $parentnode_id));
    }

    /////////////////////////////////////////////////////////////////////////////    
    // getSharedLeafObjectIDsOfTwoLeafLists - find and return an array of leaf
    // object IDs that appear in both leaf lists supplied.
    // Does not load anything from the database - it is assumed that $leafs1 and
    // $leafs2 are arrays of Leaf objects.
    public static function getSharedLeafObjectIDsOfTwoLeafLists($leafs1, $leafs2) {
        $tmpObjectIDs = array();
        foreach ($leafs1 as $leaf1) {
            foreach ($leafs2 as $leaf2) {
                if ($leaf1->getObjectID() == $leaf2->getObjectID()) {
                    if (!array_key_exists($leaf1->getObjectID(), $tmpObjectIDs)) {
                        $tmpObjectIDs[$leaf1->getObjectID()] = $leaf1->getObjectID();
                        //array_push($commonLeafObjects, $leaf1['object_id']);
                    }
                }
            }
        }
        return $tmpObjectIDs;
    }



    /////////////////////////////////////////////////////////////////////////////
    public static function printLeafsData($leafs, $desc = "") {
        print($desc . "\n");
        $i = 0;
        foreach ($leafs as $leaf) {
            $i++;
            $leaf->printLeafData("Leaf " . $i);
        }
        print(count($leafs) . " leafs\n");
    }


}
